package org.me.stepapp.persistence;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;

public class LocationDBAdapter implements LocationDBInterface{

    private Context context=null;

    private static final String TAG = "DBAdapter";
    private static final String DATABASE_NAME = "locations";
    private static final String DATABASE_TABLE = "location";
    private static final int DATABASE_VERSION = 1;
    private static final String DATABASE_CREATE =
            "create table "+DATABASE_TABLE
            +" (" + Location.KEY_ROWID+ " integer primary key autoincrement, "
            + Location.KEY_TIMESTAMP +" text not null,"
            + Location.KEY_LATITUDE+"  text not null, "
            + Location.KEY_LONGITUDE +" text not null);";
    
    // SQLite DB and DBHelper objects
    private DatabaseHelper DBHelper;
    private SQLiteDatabase db;

    public LocationDBAdapter(Context ctx){
        this.context = ctx;
        DBHelper = new DatabaseHelper(context);
    }

    /*Open the database*/
    public LocationDBAdapter open() throws SQLException{
        db = DBHelper.getWritableDatabase();

        return this;
    }

    /* Closes the database */
    public void close(){
        DBHelper.close();
    }

    /*Insert timestamp into database */
    public long insertTimestamp(String timestamp, String latitude, String longitude ){
        ContentValues initialValues = new ContentValues();
        initialValues.put(Location.KEY_TIMESTAMP, timestamp);
        initialValues.put(Location.KEY_LATITUDE, latitude);
        initialValues.put(Location.KEY_LONGITUDE, longitude);
        return db.insert(DATABASE_TABLE, null, initialValues);
    }

    /* Define database schema to populate rows */
    public static final  String[] LOCATION_SCHEMA=new String[] {
        Location.KEY_ROWID,
        Location.KEY_TIMESTAMP,
        Location.KEY_LATITUDE,
        Location.KEY_LONGITUDE
    };

    /*  Retrieve all locations in database */
    public Cursor getAllLocations() {
        return db.query(DATABASE_TABLE, 
                LOCATION_SCHEMA,
                null,
                null,
                null,
                null,
                null);
    }

    /* Retrieve a particular timestamp based on cursor */
    public Cursor getTimestamp (long rowId) throws SQLException {
        Cursor mCursor = db.query(true,
                DATABASE_TABLE,
                LOCATION_SCHEMA,
                Location.KEY_ROWID + "=" + rowId,
                null,
                null,
                null,
                null,
                null);
        if (mCursor != null) {
            mCursor.moveToFirst();
        }
        return mCursor;
    }

    /* Retruns location based on id */
    public Location getLocation(long rowId) {
        Cursor mCursor = db.query(true,
            DATABASE_TABLE,
            LOCATION_SCHEMA,
            Location.KEY_ROWID + "=" + rowId,
            null,
            null,
            null,
            null,
            null);
        if (mCursor != null) {
            mCursor.moveToFirst();
            return getLocationFromCursor( mCursor);
        }
        return null;
    }

    /* Insert Location */
    public long insertLocation(Location x) {
        if ( x!=null)  return insertLocation( x.getTimestamp(), x.getLatitude(), x.getLongitude());
        return -1;
    }

    /*  Insert Location  */
    public long insertLocation(String timestamp, String latitude, String longitude) {
        ContentValues initialValues = new ContentValues();
        initialValues.put(Location.KEY_TIMESTAMP, timestamp);
        initialValues.put(Location.KEY_LATITUDE, latitude);
        initialValues.put(Location.KEY_LONGITUDE, longitude);
        //the row ID of the newly inserted row, or -1 if an error occurred
        return db.insert(DATABASE_TABLE, null, initialValues);
    }

    /* Retrieve all locations in database */
    public List<Location> retrieveAllLocations() {
        Cursor c = db.query(DATABASE_TABLE,
            LOCATION_SCHEMA,
            null,
            null,
            null,
            null,
            null);
        ArrayList<Location> tlist=new ArrayList<Location>();
        if (c.moveToFirst()){
            do {
                tlist.add( getLocationFromCursor(  c ) );
            } while (c.moveToNext());
        }
        return tlist;
    }
    
    /* Retrieve locations under specified conditions */
    public List<Location> retrieveLocations(String where) {
        Cursor c=db.query(DATABASE_TABLE, LOCATION_SCHEMA,
                null,
                null,
                null,
                null,
                null);

                ArrayList<Location> tlist=new ArrayList<Location>();
                if (c.moveToFirst())
                {
                    do {
                        tlist.add( getLocationFromCursor(  c ) );
                    } while (c.moveToNext());
                }
         return tlist;
    }


    /* Return location at specified cursor */
    public Location getLocationFromCursor( Cursor c)
    {
        Location x= new Location(
            c.getString(Location.TIMESTAMP_ID),
            c.getString(Location.LATITUDE_ID),
            c.getString(Location.LONGITUDE_ID));
        x.setId(c.getInt(c.getInt(Location._ID)));
      return x;
    }

    /* Delete a timestamp based on row id */
    public boolean deleteTimestamp(long rowId){
        return deleteLocation(rowId);
    }

    /*  Delete location based on location */
    public boolean deleteLocation(Location x) {
        if ( x != null )  {
            return deleteLocation( x.getId());
        }
        return false;
    }

    /* Delete location based on id */
    public boolean deleteLocation(long id) {
        return db.delete(DATABASE_TABLE, Location.KEY_ROWID + "=" + id, null) > 0;
    }

    /*  Delete All locations */
    public boolean deleteAllLocations() {
        // arg0 = uri
        // arg1 = selection
        // arg2 = selectionArgs
        int count=0;
        count = db.delete(
            DATABASE_TABLE,
            null,
            null);
        return true;
    }

    /* Update locations */
    public void onUpdateLocations() {
        //  dummy       
    }

    /* Updates location */
    public boolean updateLocation(long rowId, Location x){
        if ( x != null )  {
            return updateLocation( rowId, x.getTimestamp(), x.getLatitude(), x.getLongitude());
        }
        return false;
    }

    public boolean updateLocation(long rowId, String timestamp, String latitude, String longitude)  {
        ContentValues args = new ContentValues();
        args.put(Location.KEY_TIMESTAMP, timestamp);
        args.put(Location.KEY_LATITUDE, latitude);
        args.put(Location.KEY_LONGITUDE, longitude);
        return db.update(DATABASE_TABLE, args, Location.KEY_ROWID + "=" + rowId, null) > 0;
    }

    //------------ low level sql
    public Cursor query( String rowId,  String selection, String[] selectionArgs, String sortOrder) {
        SQLiteQueryBuilder sqlBuilder = new SQLiteQueryBuilder();
        sqlBuilder.setTables(DATABASE_TABLE);

        if ( rowId!=null )  {
            //---if getting a particular location---
            sqlBuilder.appendWhere(Location.KEY_ROWID + " = " + rowId);
        }
        if (sortOrder==null || sortOrder=="")  {
            sortOrder = Location.KEY_TIMESTAMP;
        }
      Cursor c = sqlBuilder.query(
         db,
         LOCATION_SCHEMA,
         selection,
         selectionArgs,
         null,
         null,
         sortOrder);
      return c;
   }

    public long insertLocation(  ContentValues values) {
        return db.insert(DATABASE_TABLE, "", values);
    }

    
    /* Delete location using query */
    public long deleteLocations(  String whereClause, String[] whereArgs ) {
        return   db.delete(
               DATABASE_TABLE,
               whereClause,
               whereArgs);
    }

    /* Update using query */
    public int update( ContentValues values, String selection, String[] selectionArgs) {
        int count = 0;
        count = db.update(DATABASE_TABLE, values, selection, selectionArgs);
        return count;
    }


    // the SQLiteOpenHelper inner class provides basic services to supports database
    private static class DatabaseHelper extends SQLiteOpenHelper    {
        DatabaseHelper(Context context){
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db){
            db.execSQL(DATABASE_CREATE);
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
            Log.w(TAG, "Upgrading database from version " + oldVersion
                  + " to "
                  + newVersion + ", which will destroy all old data");
            db.execSQL("DROP TABLE IF EXISTS titles");
            onCreate(db);
        }
    }
}
